package rexsee.core.animation;

import java.lang.reflect.Field;

import rexsee.core.browser.Browser;
import rexsee.core.utilities.Utilities;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationSet;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.AnticipateOvershootInterpolator;
import android.view.animation.BounceInterpolator;
import android.view.animation.CycleInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;

public class AnimationStyleSheet {

	public String styleText = "";

	public String id = "";
	public String width = "0";
	public String height = "0";
	public String background_color = "#888888";

	public String animation_type = "none"; //none||rotate|alpha|scale|translate|rotate_3dx|rotate_3dy|skew
	public String animation_repeat = "repeat"; //repeat|none
	public String animation_start_sound = "";
	public String animation_repeat_sound = "";
	public String animation_end_sound = "";
	public String animation_post_start = "end"; //start|end
	public String animation_post_z = "normal"; //normal|reverse

	public String animation_center = ""; //Shortcut
	public String animation_center_x = ""; //Shortcut
	public String animation_center_y = ""; //Shortcut
	public String animation_duration = "2000";//Shortcut
	public String animation_repeat_count = "0";//Shortcut
	public String animation_repeat_mode = "normal"; //Shortcut
	public String animation_start_time = "0";//Shortcut
	public String animation_interpolator = "none";

	public String animation_rotate_3dy = ""; //Shortcut
	public String animation_rotate_3dy_from = "0";
	public String animation_rotate_3dy_to = "0";
	public String animation_rotate_3dy_depth_z = "0";
	public String animation_rotate_3dy_reverse = "false";
	public String animation_rotate_3dy_center_x = "50%";
	public String animation_rotate_3dy_center_y = "50%";
	public String animation_rotate_3dy_duration = "2000";
	public String animation_rotate_3dy_repeat_count = "0";
	public String animation_rotate_3dy_repeat_mode = "normal"; //normal|reverse
	public String animation_rotate_3dy_start_time = "0";
	public String animation_rotate_3dy_interpolator = "none";

	public String animation_rotate_3dx = ""; //Shortcut
	public String animation_rotate_3dx_from = "0";
	public String animation_rotate_3dx_to = "0";
	public String animation_rotate_3dx_depth_z = "0";
	public String animation_rotate_3dx_reverse = "false";
	public String animation_rotate_3dx_center_x = "50%";
	public String animation_rotate_3dx_center_y = "50%";
	public String animation_rotate_3dx_duration = "2000";
	public String animation_rotate_3dx_repeat_count = "0";
	public String animation_rotate_3dx_repeat_mode = "normal"; //normal|reverse
	public String animation_rotate_3dx_start_time = "0";
	public String animation_rotate_3dx_interpolator = "none";

	public String animation_skew = ""; //Shortcut
	public String animation_skew_x_from = "0";
	public String animation_skew_x_to = "0";
	public String animation_skew_y_from = "0";
	public String animation_skew_y_to = "0";
	public String animation_skew_depth_z = "0";
	public String animation_skew_reverse = "false";
	public String animation_skew_center_x = "50%";
	public String animation_skew_center_y = "50%";
	public String animation_skew_duration = "2000";
	public String animation_skew_repeat_count = "0";
	public String animation_skew_repeat_mode = "normal"; //normal|reverse
	public String animation_skew_start_time = "0";
	public String animation_skew_interpolator = "none";

	public String animation_rotate = ""; //Shortcut
	public String animation_rotate_from = "0";
	public String animation_rotate_to = "0";
	public String animation_rotate_center_x = "50%";
	public String animation_rotate_center_y = "50%";
	public String animation_rotate_duration = "2000";
	public String animation_rotate_repeat_count = "0";
	public String animation_rotate_repeat_mode = "normal"; //normal|reverse
	public String animation_rotate_start_time = "0";
	public String animation_rotate_interpolator = "none";

	public String animation_alpha = ""; //Shortcut
	public String animation_alpha_from = "0";
	public String animation_alpha_to = "0";
	public String animation_alpha_duration = "2000";
	public String animation_alpha_repeat_count = "0";
	public String animation_alpha_repeat_mode = "normal"; //normal|reverse
	public String animation_alpha_start_time = "0";
	public String animation_alpha_interpolator = "none";

	public String animation_scale = ""; //Shortcut
	public String animation_scale_x_from = "1";
	public String animation_scale_x_to = "1";
	public String animation_scale_y_from = "1";
	public String animation_scale_y_to = "1";
	public String animation_scale_center_x = "50%";
	public String animation_scale_center_y = "50%";
	public String animation_scale_duration = "2000";
	public String animation_scale_repeat_count = "0";
	public String animation_scale_repeat_mode = "normal"; //normal|reverse
	public String animation_scale_start_time = "0";
	public String animation_scale_interpolator = "none";

	public String animation_translate = ""; //Shortcut
	public String animation_translate_x_from = "1";
	public String animation_translate_x_to = "1";
	public String animation_translate_y_from = "1";
	public String animation_translate_y_to = "1";
	public String animation_translate_duration = "2000";
	public String animation_translate_repeat_count = "0";
	public String animation_translate_repeat_mode = "normal"; //normal|reverse
	public String animation_translate_start_time = "0";
	public String animation_translate_interpolator = "none";

	private final Browser mBrowser;
	private final Context mContext;
	private String[] split(String value, int n) {
		if (n <= 0) return null;
		String[] rtn = new String[n];
		String[] v = value.split("\\ ");
		rtn[0] = v[0];
		for (int i = 1; i < n; i++) {
			if (v.length > i) rtn[i] = v[i];
			else rtn[i] = rtn[i - 1];
		}
		return rtn;
	}

	public AnimationStyleSheet(Browser browser) {
		mBrowser = browser;
		mContext = browser.getContext();
	}

	public AnimationStyleSheet parseStyle(String style) {
		if (style == null || style.equals("")) return this;
		styleText = style;
		String[] argus = style.split(";");
		for (int i = 0; i < argus.length; i++) {
			if (argus[i].indexOf(":") <= 0) continue;
			String key = argus[i].substring(0, argus[i].indexOf(":")).trim().toLowerCase().replaceAll("\\-", "\\_");
			String value = argus[i].substring(argus[i].indexOf(":") + 1).trim();
			if (value.length() == 0) continue;
			if (key.equals("animation_center")) {
				String[] tmp = split(value, 2);
				animation_center_x = tmp[0];
				animation_skew_center_x = tmp[0];
				animation_rotate_3dy_center_x = tmp[0];
				animation_rotate_3dx_center_x = tmp[0];
				animation_rotate_center_x = tmp[0];
				animation_scale_center_x = tmp[0];
				animation_center_y = tmp[1];
				animation_skew_center_y = tmp[1];
				animation_rotate_3dy_center_y = tmp[1];
				animation_rotate_3dx_center_y = tmp[1];
				animation_rotate_center_y = tmp[1];
				animation_scale_center_y = tmp[1];
			} else if (key.equals("animation_center_x")) {
				animation_skew_center_x = value;
				animation_rotate_3dy_center_x = value;
				animation_rotate_3dx_center_x = value;
				animation_rotate_center_x = value;
				animation_scale_center_x = value;
			} else if (key.equals("animation_center_y")) {
				animation_skew_center_y = value;
				animation_rotate_3dy_center_y = value;
				animation_rotate_3dx_center_y = value;
				animation_rotate_center_y = value;
				animation_scale_center_y = value;
			} else if (key.equals("animation_duration")) {
				animation_duration = value;
				animation_skew_duration = value;
				animation_rotate_3dy_duration = value;
				animation_rotate_3dx_duration = value;
				animation_rotate_duration = value;
				animation_alpha_duration = value;
				animation_scale_duration = value;
				animation_translate_duration = value;
			} else if (key.equals("animation_start_time")) {
				animation_start_time = value;
				animation_skew_start_time = value;
				animation_rotate_3dy_start_time = value;
				animation_rotate_3dx_start_time = value;
				animation_rotate_start_time = value;
				animation_alpha_start_time = value;
				animation_scale_start_time = value;
				animation_translate_start_time = value;
			} else if (key.equals("animation_interpolator")) {
				animation_interpolator = value;
				animation_skew_interpolator = value;
				animation_rotate_3dy_interpolator = value;
				animation_rotate_3dx_interpolator = value;
				animation_rotate_interpolator = value;
				animation_alpha_interpolator = value;
				animation_scale_interpolator = value;
				animation_translate_interpolator = value;
			} else if (key.equals("animation_repeat_count")) {
				animation_repeat_count = value;
				animation_skew_repeat_count = value;
				animation_rotate_3dy_repeat_count = value;
				animation_rotate_3dx_repeat_count = value;
				animation_rotate_repeat_count = value;
				animation_alpha_repeat_count = value;
				animation_scale_repeat_count = value;
				animation_translate_repeat_count = value;
			} else if (key.equals("animation_repeat_mode")) {
				animation_repeat_mode = value;
				animation_skew_repeat_mode = value;
				animation_rotate_3dy_repeat_mode = value;
				animation_rotate_3dx_repeat_mode = value;
				animation_rotate_repeat_mode = value;
				animation_alpha_repeat_mode = value;
				animation_scale_repeat_mode = value;
				animation_translate_repeat_mode = value;
			} else if (key.equals("animation_rotate")) {
				String[] tmp = split(value, 2);
				animation_rotate_from = tmp[0];
				animation_rotate_to = tmp[1];
			} else if (key.equals("animation_rotate_3dy")) {
				String[] tmp = split(value, 2);
				animation_rotate_3dy_from = tmp[0];
				animation_rotate_3dy_to = tmp[1];
			} else if (key.equals("animation_rotate_3dx")) {
				String[] tmp = split(value, 2);
				animation_rotate_3dx_from = tmp[0];
				animation_rotate_3dx_to = tmp[1];
			} else if (key.equals("animation_rotate")) {
				String[] tmp = split(value, 2);
				animation_rotate_from = tmp[0];
				animation_rotate_to = tmp[1];
			} else if (key.equals("animation_alpha")) {
				String[] tmp = split(value, 2);
				animation_alpha_from = tmp[0];
				animation_alpha_to = tmp[1];
			} else if (key.equals("animation_scale")) {
				String[] tmp = split(value, 4);
				animation_scale_x_from = tmp[0];
				animation_scale_y_from = tmp[1];
				animation_scale_x_to = tmp[2];
				animation_scale_y_to = tmp[3];
			} else if (key.equals("animation_skew")) {
				String[] tmp = split(value, 4);
				animation_skew_x_from = tmp[0];
				animation_skew_y_from = tmp[1];
				animation_skew_x_to = tmp[2];
				animation_skew_y_to = tmp[3];
			} else if (key.equals("animation_translate")) {
				String[] tmp = split(value, 4);
				animation_translate_x_from = tmp[0];
				animation_translate_y_from = tmp[1];
				animation_translate_x_to = tmp[2];
				animation_translate_y_to = tmp[3];
			} else {
				try {
					this.getClass().getField(key).set(this, value);
				} catch (Exception e) {
				}
			}
		}
		return this;
	}
	public String getStyle(String name) {
		name = name.replaceAll("\\-", "\\_");
		try {
			return (String) this.getClass().getField(name).get(this);
		} catch (Exception e) {
			return null;
		}
	}
	@Override
	public AnimationStyleSheet clone() {
		AnimationStyleSheet rtn = new AnimationStyleSheet(mBrowser);
		Field[] fields = this.getClass().getFields();
		for (int i = 0; i < fields.length; i++) {
			try {
				fields[i].set(rtn, fields[i].get(this));
			} catch (Exception e) {
			}
		}
		return rtn;
	}

	public void animate(final View view) {
		animate(view, null);
	}
	public void animate(final View view, AnimationListener replaceListener) {
		if (animation_type.trim().equalsIgnoreCase("none")) return;
		if (view == null) return;
		width = String.valueOf(view.getWidth());
		height = String.valueOf(view.getHeight());
		final Animation animation = getAnimation();
		if (animation == null) return;
		if (replaceListener != null) animation.setAnimationListener(replaceListener);
		((Activity) mContext).runOnUiThread(new Runnable() {
			@Override
			public void run() {
				try {
					view.startAnimation(animation);
				} catch (Exception e) {
				}
			}
		});
	}

	public AnimationSet getAnimation() {
		AnimationSet animation = new AnimationSet(true);
		String[] types = animation_type.split("\\+");
		int length = 0;
		for (int i = 0; i < types.length; i++) {
			Animation a;
			if (types[i].equalsIgnoreCase("skew")) {
				a = getSkewAnimation();
			} else if (types[i].equalsIgnoreCase("rotate_3dy")) {
				a = getRotate3dyAnimation();
			} else if (types[i].equalsIgnoreCase("rotate_3dx")) {
				a = getRotate3dxAnimation();
			} else if (types[i].equalsIgnoreCase("rotate")) {
				a = getRotateAnimation();
			} else if (types[i].equalsIgnoreCase("alpha")) {
				a = getAlphaAnimation();
			} else if (types[i].equalsIgnoreCase("scale")) {
				a = getScaleAnimation();
			} else if (types[i].equalsIgnoreCase("translate")) {
				a = getTranslateAnimation();
			} else {
				a = null;
			}
			if (a != null) {
				animation.addAnimation(a);
				length++;
			}
		}
		if (length == 0) return null;
		animation.setAnimationListener(new AnimationListener() {
			@Override
			public void onAnimationStart(Animation animation) {
				Utilities.playSound(mContext, animation_start_sound);
				mBrowser.eventList.run(Browser.EVENT_ONANIMATIONSTART, new String[]{id});
			}
			@Override
			public void onAnimationRepeat(Animation animation) {
				Utilities.playSound(mContext, animation_repeat_sound);
				mBrowser.eventList.run(Browser.EVENT_ONANIMATIONREPEAT, new String[]{id});
			}
			@Override
			public void onAnimationEnd(Animation animation) {
				Utilities.playSound(mContext, animation_end_sound);
				mBrowser.eventList.run(Browser.EVENT_ONANIMATIONEND, new String[]{id});
			}
		});
		int w = Utilities.getInt(width, 0);
		int h = Utilities.getInt(height, 0);
		animation.initialize(w, h, w, h);
		return animation;
	}

	private Animation getRotateAnimation() {
		Animation animation = null;
		try {
			float rotateCenterX = getCenterValue(animation_rotate_center_x);
			float rotateCenterY = getCenterValue(animation_rotate_center_y);
			int from = Integer.parseInt(animation_rotate_from);
			int to = Integer.parseInt(animation_rotate_to);
			animation = new RotateAnimation(from, to, Animation.RELATIVE_TO_SELF, rotateCenterX, Animation.RELATIVE_TO_SELF, rotateCenterY);
			animation.setDuration(Integer.parseInt(animation_rotate_duration));
			animation.setRepeatCount(Integer.parseInt(animation_rotate_repeat_count));
			animation.setRepeatMode(animation_rotate_repeat_mode.equalsIgnoreCase("normal") ? 1 : 2);
			animation.setStartOffset(Utilities.getLong(animation_rotate_start_time, 0));
			animation.setInterpolator(getInterPolator(animation_rotate_interpolator));
		} catch (Exception e) {
		}
		return animation;
	}
	private Animation getAlphaAnimation() {
		Animation animation = null;
		try {
			float from = Float.parseFloat(animation_alpha_from.replaceAll("%", "")) / 100;
			float to = Float.parseFloat(animation_alpha_to.replaceAll("%", "")) / 100;
			animation = new AlphaAnimation(from, to);
			animation.setDuration(Integer.parseInt(animation_alpha_duration));
			animation.setRepeatCount(Integer.parseInt(animation_alpha_repeat_count));
			animation.setRepeatMode(animation_alpha_repeat_mode.equalsIgnoreCase("normal") ? 1 : 2);
			animation.setStartOffset(Utilities.getLong(animation_alpha_start_time, 0));
			animation.setInterpolator(getInterPolator(animation_alpha_interpolator));
		} catch (Exception e) {
		}
		return animation;
	}
	private Animation getScaleAnimation() {
		Animation animation = null;
		try {
			float scaleCenterX = getCenterValue(animation_scale_center_x);
			float scaleCenterY = getCenterValue(animation_scale_center_y);
			float fromX = Float.parseFloat(animation_scale_x_from);
			float toX = Float.parseFloat(animation_scale_x_to);
			float fromY = Float.parseFloat(animation_scale_y_from);
			float toY = Float.parseFloat(animation_scale_y_to);
			animation = new ScaleAnimation(fromX, toX, fromY, toY, Animation.RELATIVE_TO_SELF, scaleCenterX, Animation.RELATIVE_TO_SELF, scaleCenterY);
			animation.setDuration(Integer.parseInt(animation_scale_duration));
			animation.setRepeatCount(Integer.parseInt(animation_scale_repeat_count));
			animation.setRepeatMode(animation_scale_repeat_mode.equalsIgnoreCase("normal") ? 1 : 2);
			animation.setStartOffset(Utilities.getLong(animation_scale_start_time, 0));
			animation.setInterpolator(getInterPolator(animation_scale_interpolator));
		} catch (Exception e) {
		}
		return animation;
	}
	private Animation getTranslateAnimation() {
		Animation animation = null;
		try {
			float fromX = Float.parseFloat(animation_translate_x_from);
			float toX = Float.parseFloat(animation_translate_x_to);
			float fromY = Float.parseFloat(animation_translate_y_from);
			float toY = Float.parseFloat(animation_translate_y_to);
			fromX = fromX / 100;
			toX = toX / 100;
			fromY = fromY / 100;
			toY = toY / 100;
			animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, fromX, Animation.RELATIVE_TO_SELF, toX, Animation.RELATIVE_TO_SELF, fromY, Animation.RELATIVE_TO_SELF, toY);
			animation.setDuration(Integer.parseInt(animation_translate_duration));
			animation.setRepeatCount(Integer.parseInt(animation_translate_repeat_count));
			animation.setRepeatMode(animation_translate_repeat_mode.equalsIgnoreCase("normal") ? 1 : 2);
			animation.setStartOffset(Utilities.getLong(animation_translate_start_time, 0));
			animation.setInterpolator(getInterPolator(animation_translate_interpolator));
		} catch (Exception e) {
		}
		return animation;
	}
	private Animation getRotate3dyAnimation() {
		Animation animation = null;
		try {
			float rotateCenterX = getCenterValue(animation_rotate_3dy_center_x);
			float rotateCenterY = getCenterValue(animation_rotate_3dy_center_y);
			float from = Utilities.getFloat(animation_rotate_3dy_from, 0f);
			float to = Utilities.getFloat(animation_rotate_3dy_to, 90f);
			float rotate3DDepthZ = Utilities.getFloat(animation_rotate_3dy_depth_z, 310.0f);
			boolean reverse = (animation_rotate_3dy_reverse.equalsIgnoreCase("true")) ? true : false;
			animation = new Rotate3dyAnimation(from, to, rotate3DDepthZ, reverse, Animation.RELATIVE_TO_SELF, rotateCenterX, Animation.RELATIVE_TO_SELF, rotateCenterY);
			animation.setDuration(Utilities.getInt(animation_rotate_3dy_duration, 1000));
			animation.setRepeatCount(Utilities.getInt(animation_rotate_3dy_repeat_count, 0));
			animation.setRepeatMode(animation_rotate_3dy_repeat_mode.equalsIgnoreCase("normal") ? 1 : 2);
			animation.setStartOffset(Utilities.getLong(animation_rotate_3dy_start_time, 0));
			animation.setInterpolator(getInterPolator(animation_rotate_3dy_interpolator));
		} catch (Exception e) {
		}
		return animation;
	}
	private Animation getRotate3dxAnimation() {
		Animation animation = null;
		try {
			float rotateCenterX = getCenterValue(animation_rotate_3dx_center_x);
			float rotateCenterY = getCenterValue(animation_rotate_3dx_center_y);
			float from = Utilities.getFloat(animation_rotate_3dx_from, 0f);
			float to = Utilities.getFloat(animation_rotate_3dx_to, 90f);
			float rotate3DDepthZ = Utilities.getFloat(animation_rotate_3dx_depth_z, 310.0f);
			boolean reverse = (animation_rotate_3dx_reverse.equalsIgnoreCase("true")) ? true : false;
			animation = new Rotate3dxAnimation(from, to, rotate3DDepthZ, reverse, Animation.RELATIVE_TO_SELF, rotateCenterX, Animation.RELATIVE_TO_SELF, rotateCenterY);
			animation.setDuration(Utilities.getInt(animation_rotate_3dx_duration, 1000));
			animation.setRepeatCount(Utilities.getInt(animation_rotate_3dx_repeat_count, 0));
			animation.setRepeatMode(animation_rotate_3dx_repeat_mode.equalsIgnoreCase("normal") ? 1 : 2);
			animation.setStartOffset(Utilities.getLong(animation_rotate_3dx_start_time, 0));
			animation.setInterpolator(getInterPolator(animation_rotate_3dx_interpolator));
		} catch (Exception e) {
		}
		return animation;
	}
	private Animation getSkewAnimation() {
		Animation animation = null;
		try {
			float skewCenterX = getCenterValue(animation_skew_center_x);
			float skewCenterY = getCenterValue(animation_skew_center_y);
			float fromX = Utilities.getFloat(animation_skew_x_from, 0f);
			float toX = Utilities.getFloat(animation_skew_x_to, 1f);
			float fromY = Utilities.getFloat(animation_skew_y_from, 0f);
			float toY = Utilities.getFloat(animation_skew_y_to, 1f);
			float skewDepthZ = Utilities.getFloat(animation_skew_depth_z, 310.0f);
			boolean reverse = (animation_skew_reverse.equalsIgnoreCase("true")) ? true : false;
			animation = new SkewAnimation(fromX, toX, fromY, toY, skewDepthZ, reverse, Animation.RELATIVE_TO_SELF, skewCenterX, Animation.RELATIVE_TO_SELF, skewCenterY);
			animation.setDuration(Utilities.getInt(animation_skew_duration, 1000));
			animation.setRepeatCount(Utilities.getInt(animation_skew_repeat_count, 0));
			animation.setRepeatMode(animation_skew_repeat_mode.equalsIgnoreCase("normal") ? 1 : 2);
			animation.setStartOffset(Utilities.getLong(animation_skew_start_time, 0));
			animation.setInterpolator(getInterPolator(animation_skew_interpolator));
		} catch (Exception e) {
		}
		return animation;
	}

	private static Interpolator getInterPolator(String name) {
		if (name.equalsIgnoreCase("AccelerateDecelerate")) {
			return new AccelerateDecelerateInterpolator();
		} else if (name.equalsIgnoreCase("Accelerate")) {
			return new AccelerateInterpolator(10.0f);
		} else if (name.equalsIgnoreCase("Decelerate")) {
			return new DecelerateInterpolator(10.0f);
		} else if (name.equalsIgnoreCase("Anticipate")) {
			return new AnticipateInterpolator(1.0f);
		} else if (name.equalsIgnoreCase("AnticipateOvershoot")) {
			return new AnticipateOvershootInterpolator(1.0f, 1.5f);
		} else if (name.equalsIgnoreCase("Overshoot")) {
			return new OvershootInterpolator(1.0f);
		} else if (name.equalsIgnoreCase("Bounce")) {
			return new BounceInterpolator();
		} else if (name.equalsIgnoreCase("Cycle")) {
			return new CycleInterpolator(1);
		} else if (name.equalsIgnoreCase("Linear")) {
			return new LinearInterpolator();
		} else {
			return new LinearInterpolator();
		}
	}
	private static float getCenterValue(String styleValue) {
		try {
			float rtn = Float.parseFloat(styleValue.replaceAll("%", ""));
			rtn = rtn / 100;
			if (rtn < 0) rtn = 0;
			if (rtn > 1) rtn = 1;
			return rtn;
		} catch (Exception e) {
			return (float) 0.5;
		}
	}

}
